home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / ddj1291.zip / STAT.ZIP / SOURCE.ZIP / PAMSDOS.C < prev    next >
C/C++ Source or Header  |  1990-05-09  |  10KB  |  309 lines

  1. /*
  2. ** File:    pamsdos.c
  3. **
  4. **        Copyright 1990
  5. **        Fred Motteler and Applied Microsystems Corporation
  6. **        All Rights Reserved
  7. **
  8. ** Description:    Utility functions used by the MS-DOS version of the
  9. **        statistical performance analysis package.
  10. */
  11.  
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <fcntl.h>
  15. #include <string.h>
  16. #include "padef.h"
  17.  
  18. /*
  19. ** Function:    int main( argcN, argvAS )
  20. **
  21. ** Description:    MS-DOS based statistical performance analysis program.
  22. **
  23. **        Command line arguments:
  24. **
  25. **            pamsdos prog.map prog.cfg prog.exe options
  26. **
  27. **        Where:    prog.map    memory map for program
  28. **            prog.cfg    memory map configuration
  29. **            prog.exe    program to run
  30. **            options        command options for the program to run
  31. */    
  32. int
  33. main( argcN, argvAS )
  34. int argcN;
  35. char *argvAS[];
  36. {
  37.     int errorN;            /* Error code */
  38.     unsigned int segmentW;    /* Starting load address of program to run */
  39.     unsigned int offsetW;
  40.     unsigned long originL;
  41.     int processedN;        /* Number of map globals processed */
  42.     int i;            /* General index */
  43.     FILE *mapFP;        /* Map file to read */
  44.     FILE *formatFP;        /* File with map file format information */
  45.     char commandAC[PA_LINE_LEN]; /* Complete command line for program */
  46.     int pagelinesN;        /* Number of lines on output page, 0 if
  47.                  * continuous, -1 if no display output, else
  48.                  * n if n lines per page. */
  49.     FILE *listFP;        /* Results output file */
  50.     char listAB[80];        /* Optional results listing file path/name */
  51.     char pagelinesAB[8];    /* String for number of lines/page */
  52.  
  53.     printf("pamsdos - Statistical performance analysis tool for MS-DOS\n");
  54.     printf("Version %s\n", PA_VERSION);
  55.     printf("Copyright (C) 1990  Fred Motteler and Applied Microsystems Corporation\n");
  56.     if (argcN < 4)
  57.     {
  58.     printf("Usage: pamsdos prog.map prog.cfg prog.exe [options]\n");
  59.     printf("    Where:  prog.map    memory map for program\n");
  60.     printf("            prog.cfg    memory map configuration file\n");
  61.     printf("            prog.exe    program to run\n");
  62.     printf("            [options]   command line options for the program to run\n");
  63.     exit(-100);
  64.     }
  65.  
  66.     /* Determine where the program to run is to be located. */
  67.     if ((errorN = pa_locate(&segmentW, &offsetW)) != 0)
  68.     {
  69.     pa_error(errorN);
  70.     exit(errorN);
  71.     }
  72.     /* Calculate origin of program.  Room must be allowed for memory
  73.      * malloc()'d off the heap. */
  74.     originL = (unsigned long) (segmentW + 1);
  75.     originL <<= 4;
  76.     originL += (unsigned long) (offsetW - 2);
  77.     originL += (unsigned long) (PA_BUFLEN << 2);
  78.  
  79.     if ((pa_debugN & PA_GENERAL) != 0)
  80.     {
  81.     printf("program start segment:offset %x:%x\n", segmentW, offsetW);
  82.     printf("              linear address %lx\n",originL);
  83.     }
  84.  
  85.     /* Get the complete command line to invoke the program. */
  86.     strcpy(commandAC, argvAS[3]);
  87.     if (argcN > 4)
  88.     {
  89.     for (i = 4; i <  argcN; i++)
  90.     {
  91.         strcat(commandAC," ");
  92.         strcat(commandAC,argvAS[i]);
  93.     }
  94.     }
  95.  
  96.     /* Run the program and collect samples. */
  97.     printf("Starting %s\n", argvAS[3]);
  98.     if ((errorN = pa_pcsample(commandAC, PA_SAMPLE, PA_BUFLEN)) != 0)
  99.     {
  100.     pa_error(errorN);
  101.     exit(errorN);
  102.     }
  103.  
  104.     /* Read in the configuration file to get map format information and
  105.      * to get number of lines / display page and option listing file. */
  106.     if ((formatFP = fopen(argvAS[2], "r")) == (FILE *) NULL)
  107.     {
  108.     pa_error(PA_NO_CFG_E);
  109.     exit(PA_NO_CFG_E);
  110.     }
  111.  
  112.     /* Read in display lines, and optional output file configuration data 
  113.      * from the configuration file. */
  114.     if (((errorN = paconfig(formatFP, PA_PAGELINES, pagelinesAB)) != 0) ||
  115.     ((errorN = paconfig(formatFP, PA_LISTFILE, listAB)) != 0))
  116.     {
  117.     pa_error(errorN);
  118.     fclose(formatFP);
  119.     exit(errorN);
  120.     }
  121.  
  122.     /* Determine the number of lines/page to display */
  123.     if (sscanf(pagelinesAB, "%d", &pagelinesN) != 1)
  124.     {
  125.     pa_error(PA_BAD_ARG_E);
  126.     fclose(formatFP);
  127.     exit(PA_BAD_ARG_E);
  128.     }
  129.  
  130.     /* Open the optional listing file */
  131.     if (listAB[0] == '\0')
  132.     listFP = (FILE *) NULL;
  133.     else if ((listFP = fopen(listAB, "w")) == (FILE *) NULL)
  134.     {
  135.     pa_error(PA_NO_LST_E);
  136.     fclose(formatFP);
  137.     exit(PA_NO_LST_E);
  138.     }
  139.  
  140.     /* Read the program's memory map and create "bins" for the program
  141.      * counter samples. */
  142.     if ((mapFP = fopen(argvAS[1], "r")) == (FILE *) NULL)
  143.     {
  144.     pa_error(PA_NO_MAP_E);
  145.     fclose(mapFP);
  146.     exit(PA_NO_MAP_E);
  147.     }
  148.     if ((errorN = pardmap(mapFP, formatFP, originL, &processedN)) != 0)
  149.     {
  150.     pa_error(errorN);
  151.     fclose(mapFP);
  152.     fclose(formatFP);
  153.     exit(errorN);
  154.     }
  155.  
  156.     /* Process the samples and sort the bins according to the PC hits in
  157.      * each bin. */
  158.     printf("Processing samples\n");
  159.     if ((errorN = pa_bstuff(PA_SAMPLE, patableAHP, &processedN)) != 0)
  160.     {
  161.     pa_error(errorN);
  162.     fclose(mapFP);
  163.     fclose(formatFP);
  164.     exit(errorN);
  165.     }
  166.  
  167.     /* Display the results */
  168.     padisply(patableAHP, processedN, pagelinesN, listFP);
  169.     fclose(mapFP);
  170.     fclose(formatFP);
  171.     exit(0);
  172. }
  173.  
  174. /*
  175. ** Function:    int pa_locate(unsigned int *segmentPW, unsigned int *offsetPW)
  176. **
  177. ** Description:    This function figures out where in memory the program to be
  178. **        analyzed is to be run.
  179. **
  180. **        MS-DOS executables are dynamically located at runtime.
  181. **        In order to avoid the complexity of writing a DOS ".exe"
  182. **        loader program, a simpler approach is used here.
  183. **
  184. **        This function uses the ANSI system() library function to
  185. **        execute a trial program, "pawhere.exe" that writes its
  186. **        starting code segment and offset to a temporary file
  187. **        "pawhere.tmp".    After "pawhere.exe" has finished, this
  188. **        function opens the temporary file and reads the starting
  189. **        segment and offset value.
  190. **
  191. **        It is assumed that the desired program to be tested will
  192. **        have the same starting code segment and offset.
  193. **
  194. **        If all operations were successful, then 0 is returned.
  195. **        Otherwise a non-zero error code will be returned.
  196. */ 
  197. int
  198. pa_locate(segmentPW, offsetPW)
  199. unsigned int *segmentPW;
  200. unsigned int *offsetPW;
  201. {
  202.     FILE *fp;
  203.  
  204.     /* First figure out where the program will be loaded.  Run "pawhere.exe"
  205.      * via a system() function call. */
  206.     if ((system("pawhere")) != 0)
  207.     return(PA_NO_WHERE_E);
  208.  
  209.     /* Read in the result of whereami.tmp. */
  210.     if ((fp = fopen("pawhere.tmp", "r")) == (FILE *) NULL)
  211.     return(PA_NO_TMP_E);
  212.     if ((fscanf(fp, "%x %x", segmentPW, offsetPW)) != 2)
  213.     return(PA_BAD_TMP_E);
  214.     fclose(fp);
  215.     if (remove("pawhere.tmp") != 0)
  216.     return(PA_TMP_RM_E);
  217.  
  218.     return(0);
  219. }
  220.  
  221. /*
  222. ** Function:    int pa_pcsample(char *programS, char *sampfileS, int samplesN)
  223. **
  224. ** Description:    This function runs the program (entire command line) pointed
  225. **        to by programS, while sampling its program counter every
  226. **        PC clock tick.  Up to samplesN program counter samples are
  227. **        collected, and then written out in binary format to the file
  228. **        sampfileS.
  229. */
  230. int
  231. pa_pcsample(programS, sampfileS, samplesN)
  232. char *programS;            /* Command line of program to run */
  233. char *sampfileS;        /* File to use to write out pc samples */
  234. int samplesN;            /* Maximum number of samples to collect */
  235. {
  236.     unsigned long *pcbufferPL;    /* Word pointer to local pc sample buffer */
  237.     unsigned int *pcbufferPW;    /* Long pointer to local pc sample buffer */
  238.     unsigned long *pcorgPL;    /* Original copy of pointer to pc sample buf */
  239.     unsigned int segmentW;    /* Starting segment of program to run */
  240.     unsigned int offsetW;    /* Starting offset of program to run */
  241.     int handleN;        /* pc sample file handle */
  242.     unsigned long sampleL;    /* segment:offset sample converted to linear */
  243.     int i;            /* general index */
  244.  
  245.     /* Grab memory for the sample buffer */
  246.     if ((pcbufferPL = (unsigned long *) malloc((4*samplesN)))
  247.     == (unsigned long *) NULL)
  248.     return(PA_NO_MEM_E);
  249.     /* Copy buffer pointer to allow word (int) access as well as long acess. */
  250.     pcbufferPW = (unsigned int *) pcbufferPL;
  251.     pcorgPL = pcbufferPL;
  252.  
  253.     /* Start CS:IP sampling */
  254.     paopen(pcbufferPW, samplesN);
  255.  
  256.     /* Run the desired program. */
  257.     if (system(programS) != 0)
  258.     {
  259.     paclose();
  260.     return(PA_NO_EXEC_E);
  261.     }
  262.  
  263.     /* Stop sampling */
  264.     samplesN = paclose();
  265.  
  266.     /* Convert the samples from offsetW:segment to linear addresses relative
  267.      * to the origin of the loaded program. */
  268.     if ((pa_debugN & PA_GENERAL) != 0)
  269.     printf("pa_pcsample: number of samples: %d\n", samplesN);
  270.     for (i = 0; i < samplesN; i++)
  271.     {
  272.     /* Read segment:offset value from the table. */
  273.     offsetW = *pcbufferPW++;
  274.     segmentW = *pcbufferPW++;
  275.  
  276.     if ((pa_debugN & PA_GENERAL) != 0)
  277.         printf("pa_pcsample: sample segment:offset %x:%x\n",
  278.             segmentW,offsetW);
  279.  
  280.     /* Convert it to a linear address. */
  281.     sampleL = ((unsigned long) offsetW)
  282.         + (((unsigned long) segmentW) << 4);
  283.     /* Write the linear address back to the table. */
  284.     *pcbufferPL++ = sampleL;
  285.     if ((pa_debugN & PA_GENERAL) != 0)
  286.         printf("pa_pcsample: linear sample %lx\n",sampleL);
  287.     }
  288.  
  289.     /* Write the samples to a binary file. */
  290.     if ((handleN = open (sampfileS, (O_CREAT | O_WRONLY | O_RAW), 0))
  291.     == (-1))
  292.     {
  293.     free(pcorgPL);
  294.     return(PA_NO_PC_FILE_E);
  295.     }
  296.     if ((write( handleN, ((char *) pcorgPL), (samplesN << 2)))
  297.     != (samplesN << 2))
  298.     {
  299.     close(handleN);
  300.     free(pcorgPL);
  301.     return(PA_NO_PC_WR_E);
  302.     }
  303.  
  304.     close(handleN);
  305.     free(pcorgPL);
  306.     return(0);
  307. }
  308.  
  309.